//! 存储工厂
//!
//! 根据配置创建不同的存储后端实例。

use nacos_core::config::{StorageConfig, StorageType};
use nacos_core::traits::Storage;
use nacos_core::Result;
use std::sync::Arc;
use crate::error::StorageError;
use crate::{FileStorage, MemoryStorage};

#[cfg(feature = "sqlite")]
use crate::sqlite::SqliteStorage;
#[cfg(feature = "mysql")]
use crate::mysql::MysqlStorage;
#[cfg(feature = "postgres")]
use crate::postgres::PostgresStorage;

/// 存储工厂
#[derive(Debug)]
pub struct StorageFactory;

impl StorageFactory {
    /// 根据配置创建新的存储实例
    pub async fn new_storage(config: &StorageConfig) -> Result<Arc<dyn Storage>> {
        match config.storage_type {
            StorageType::Memory => {
                Ok(Arc::new(MemoryStorage::new()))
            }
            StorageType::File => {
                let path = if config.connection_string.is_empty() {
                    // 提供一个默认路径
                    "nacos_data"
                } else {
                    &config.connection_string
                };
                let file_storage = FileStorage::new(path).await?;
                Ok(Arc::new(file_storage))
            }
            #[cfg(feature = "sqlite")]
            StorageType::Sqlite => {
                let sqlite_storage = SqliteStorage::new(&config.connection_string)
                    .await
                    .map_err(|e| StorageError::Connection(e.to_string()))?;
                Ok(Arc::new(sqlite_storage))
            }
            #[cfg(feature = "mysql")]
            StorageType::Mysql => {
                let mysql_storage = MysqlStorage::new(&config.connection_string)
                    .await
                    .map_err(|e| StorageError::Connection(e.to_string()))?;
                Ok(Arc::new(mysql_storage))
            }
            #[cfg(feature = "postgres")]
            StorageType::PostgreSQL => {
                let postgres_storage = PostgresStorage::new(&config.connection_string)
                    .await
                    .map_err(|e| StorageError::Connection(e.to_string()))?;
                Ok(Arc::new(postgres_storage))
            }
            #[cfg(not(all(feature = "sqlite", feature = "mysql", feature = "postgres")))]
            _ => {
                Err(StorageError::Config(format!(
                    "Unsupported storage type: {:?}. Please enable the corresponding feature.",
                    config.storage_type
                )).into())
            }
        }
    }
}
